《C++ Primer 第五版》阅读过程查漏补缺 Chapter5

这一章前半部分好像没有什么好说的,略过总结了就。主要说一下try-catch部分。

条件语句

else悬垂

这种问题是当我们嵌套使用if分支时,会出现if分支多于else分支的情况,此时else和if的匹配问题就是我们常说的悬垂问题。

C++规定,else与离他最近的尚未匹配的if进行匹配。

解决else悬垂的最好办法就是使用花括号,成块来进行匹配。

switch语句

  • case关键字和它对应的值一起被称为case标签(case label)。case标签必须是整型常量表达式。
  • default标签即使不打算做任何事情,也一定要定义这个标签。同时标签不能孤零零存在,必须跟上一条语句,或者另外一个case标签。如果switch中出现了一个空的default作为结束,那么这个default标签后面必须跟上空语句或者空块。

迭代语句

while语句

1
2
while (condition)
statement

在while结构中,只要condition求值结果为真,则一直执行statement。condition不能为空,如果condition第一次求值就是false,则statement不执行。

while的条件部分可以是一个表达式,也可以是一个带初始化的变量声明。通常应该有条件本身、或者循环体改变表达式的值,否则循环无法终止。

传统for语句

传统格式:

1
2
for (init-statement; condition ; expression)
statement

每次循环流程为:

  • init-statement 初始化(开始时执行,只执行一次)
  • 判断condition是否满足,如果不满足,马上结束循环。
  • 如果满足,执行statement
  • 将init-statement初始化的变量进行修改

init-statement也可以定义多个对象,但是只能有一个声明语句,因此所有变量的基础类型都必须相同

当然我们也可以省去expression,这样需要在条件部分或循环体中改变迭代变量的值。

范围for语句

1
2
for (declaration:expression)
statement

expression表示一个序列。包括不限于花括号括起来的初始值列表、数组、vector和string等类型的对象。这些对象公共特点是拥有能返回迭代器的begin和end成员

do while语句

1
2
3
do	
statement
while (condition)

在该种语句中,求condition前要限制性statement,condition不能为空。condition使用的变量必须定义在循坏体外,因为如果允许在条件部分定义,则不合理。

跳转语句

continue语句终止最近循环中的当前迭代开始下一次迭代。

对于范围for语句来说,就是用序列中的下一个元素初始化循环控制变量。

try-catch语句块和异常处理

c++中,异常处理包括:

  • throw表达式。异常检测部分使用throw表达式来表示他遇到了无法解决的问题。throw 引发(raise) 异常
  • try语句块和catch子句,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理,因为catch子句处理异常,他们也被称作异常处理代码
  • 一套异常类,用于在throw表达式和相关的catch字句之间传递异常的具体信息

try-catch语句块

1
2
3
4
5
6
7
try {
program-statements
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements
} // ```

try关键字后是一个块,这个块是可能存在异常的行为

try块之后是一个或多个catch子句,catch子句包括三部分:cath关键字、括号中的对象的声明(异常声明)、以及一个块。

当选中某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳到try语句块最后一个catch子句之后的语句继续执行。

复杂系统中,程序遇到异常代码前,执行路径可能已经经过了多个try语句块,就是当try语句块中调用了另一个包含有try语句块的函数,层层包含、层层嵌套的情况。

寻找处理代码和函数调用链相反,异常抛出时,首先搜索该异常的函数,如果没有匹配的catch,则终止该函数,并在调用该函数的函数中继续寻找,如果还是没有找到匹配的catch子句,新的函数也会被终止,一直搜索到找到合适类型的catch子句为止

如果最终没找到合适的catch子句,程序会转到terminate的标准库函数,该函数和系统相关,一般情况是导致程序非正常退出。

对于没有try语句块定义的异常,同样就是会转到terminate的标准库函数。

能够在异常发生期间正确执行“清理”工作的程序被称为异常安全代码,编写异常安全代码是非常困难的。

标准异常

c++标准库定义了一组类,用于报告标准库函数遇到的问题,这些异常类分别定义在4个头文件:

  • exception头文件定义了最通用的异常类。只报告异常发生,不提供额外信息
  • stdexcept头文件定义了几种常用的异常类
  • new头文件定义了bad_alloc异常类型
  • type_info头文件定义了bad_cast异常类型。

标准库异常类只定义了很少的运算,包括创建、拷贝异常类型的对象、以及为异常类型对象赋值。

我们只能以默认初始化的方式初始化exception、bad_alloc和bad_cast对象,不允许为这些对象提供初始值。

其他异常类型则应该使用string或C风格字符串初始化这些类型的对象,但不允许使用默认初始化。当创建此类对象时,必须提供初始值,即错误相关的信息。

异常类型只定义了一个what成员函数,返回值是一个C风格字符串的const char*,其目的是提供关于异常的文本信息。